using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace BlockOS.Client
{
    public class SubMesh<TVertexData>
    {
        public TVertexData[] vertices;
        public int[] indices;

        public string GetStatus()
        {
            return $"Vertices Count:{vertices.Count()},\nIndices Count:{indices.Count()}";
        }

        public void SetVertices(Func<TVertexData, TVertexData> map)
        {
            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i] = map(vertices[i]);
            }
        }

        internal SubMesh<TVertexData> Clone()
        {
            return new SubMesh<TVertexData> { vertices = vertices.ToArray(), indices = indices.ToArray() } ;
        }

        public class Builder
        {
            private List<TVertexData> vertexList = new();
            private List<int> indexList = new();
            /*   a
             *   /\
             *  /  \
             * b----c
             */
            public Builder Triangle(TVertexData a, TVertexData b, TVertexData c)
            {
                Indices(0, 2, 1);
                Vertices(a, b, c);

                return this;
            }

            /* a------b
             * |      |
             * |      |
             * c------d
             */
            public Builder Quad(TVertexData a, TVertexData b, TVertexData c, TVertexData d)
            {
                Indices(0, 3, 2, 0, 1, 3);
                Vertices(a, b, c, d);

                return this;
            }

            public Builder Vertex(TVertexData v)
            {
                vertexList.Add(v);
                return this;
            }

            public Builder EnumerableVertices(IEnumerable<TVertexData> vertices)
            {
                vertexList.AddRange(vertices);
                return this;
            }

            public Builder Vertices(params TVertexData[] vertices) => EnumerableVertices(vertices);

            public Builder Index(int i)
            {
                indexList.Add(i);
                return this;
            }

            public Builder EnumerableIndices(IEnumerable<int> indices)
            {
                indexList.AddRange(indices.Select(x => x + VertexCount));
                return this;
            }

            public Builder Indices(params int[] indices) => EnumerableIndices(indices);

            public int VertexCount => vertexList.Count;

            public Builder SubMesh(SubMesh<TVertexData> subMesh)
            {
                Indices(subMesh.indices);
                Vertices(subMesh.vertices);
                return this;
            }

            public SubMesh<TVertexData> Build()
            {
                return new SubMesh<TVertexData>
                {
                    vertices = vertexList.ToArray(),
                    indices = indexList.ToArray()
                };
            }
        }
    }
}
